package com.zsrd.lessons.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsrd.lessons.domain.*;
import com.zsrd.lessons.domain.dto.ExamDto;
import com.zsrd.lessons.domain.dto.ExamPlanDto;
import com.zsrd.lessons.domain.vo.*;
import com.zsrd.lessons.mapper.TsExamPlanMapper;
import com.zsrd.lessons.service.*;
import com.zsrd.lessons.utils.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 考试计划表 服务实现类
 * </p>
 *
 * @author Chen Wei
 * @since 2022-07-11
 */
@Service
public class TsExamPlanServiceImpl extends ServiceImpl<TsExamPlanMapper, TsExamPlan> implements TsExamPlanService {


    //题库答案
    @Autowired
    TsQuestionAnswerService tsQuestionAnswerService;

    //题库答案
    @Autowired
    TsExamPlanUserService tsExamPlanUserService;
    //题库答案
    @Autowired
    TsQuestionBankService tsQuestionBankService;
    @Autowired
    TsExamService tsExamService;
    @Autowired
    TsExamQuestionService tsExamQuestionService;

    /**
     * 新增考试计划
     *
     * @param examPlanDto
     * @return
     */
    @Transactional
    @Override
    public boolean savePlan(ExamPlanDto examPlanDto) {
        //判断 制定的该计划中人员  在这段时间内是否有考试  如果有责返回失败

        List<TsExamPlan> tsExamPlans = this.baseMapper.selectList(new QueryWrapper<TsExamPlan>()
                .eq("title", examPlanDto.getTitle())
                .eq("org_no", examPlanDto.getOrgNo())
                .eq("status","1")
                .ne(!Objects.isNull(examPlanDto.getId()),"id",examPlanDto.getId()));
        if (!ListUtils.isEmpty(tsExamPlans)) {
            throw new RuntimeException("该考试计划名称已存在");
        }

        String[] userIds = examPlanDto.getUserIds();
        Date examTime = examPlanDto.getExamTime();
        Integer limitTime = examPlanDto.getLimitTime();
        List<String> names = new ArrayList<>();

        for (String userId : userIds) {
            List<String> list = this.baseMapper.queryIsHaveExam(userId, examTime, limitTime,examPlanDto.getId());
            if (!ListUtils.isEmpty(list)) {
                names.addAll(list);
            }
        }
        if (!ListUtils.isEmpty(names)) {
            StringBuilder sb = new StringBuilder();

            for (String name : names) {
                if (!sb.toString().contains(name)) {

                    if (StringUtils.isNotEmpty(sb.toString())) {
                        sb.append(",");
                    }
                    sb.append(name);
                }
            }
            throw new RuntimeException("此时间段内," + sb.toString() + "已有考试");
        }
        int res = 0;
        if(Objects.isNull(examPlanDto.getId())){
             res = this.baseMapper.addPlan(examPlanDto);
        }else{
            TsExamPlan ts = new TsExamPlan();
            BeanUtils.copyProperties(examPlanDto,ts);
            ts.setUtime(LocalDateTime.now());
            ts.setStatus(1);
             res = this.baseMapper.updateById(ts);
             //对考试人员进行删除并重新添加
            QueryWrapper<TsExamPlanUser> queryWrapper = new QueryWrapper();
            queryWrapper.eq("pid",examPlanDto.getId());
            tsExamPlanUserService.remove(queryWrapper);
        }
        if (res > 0) {

            //写考试关联人员
            int addUserRes = this.baseMapper.addPlanUser(examPlanDto.getUserIds(), examPlanDto.getId());
//            //设置考试类型为2 正式考试
//            examPlanDto.setExamType(2);
//            //设置考试状态 0新生成
//            examPlanDto.setStatus(0);
//            //增加考试记录
//            return this.baseMapper.addExam2(examPlanDto) > 0;

        }
        return false;
    }

    /**
     * 删除考试计划
     *
     * @param examPlanDto
     * @return
     */
    @Transactional
    @Override
    public boolean delPlan(ExamPlanDto examPlanDto) {
        //先删除试卷信息ts_exam
        this.baseMapper.delExam(examPlanDto.getId());
        //再改变考试计划状态
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("id", examPlanDto.getId());
        updateWrapper.set("status", -1);
        return this.baseMapper.update(null, updateWrapper) > 0;

    }

    /**
     * 查询考试计划
     *
     * @param examPlanDto
     * @return
     */
    @Override
    public IPage<ExamPlanVo> queryExamPlan(ExamPlanDto examPlanDto) {
        IPage<ExamPlanVo> page = new Page<>(examPlanDto.getCurrent(), examPlanDto.getSize());
        IPage<ExamPlanVo> examPlanVoIPage = this.baseMapper.queryExamPlan(page, examPlanDto.getOrgNo(), examPlanDto.getKeyword());
        for (ExamPlanVo e : examPlanVoIPage.getRecords()) {
            List<ExamPlanUserVo> users = tsExamPlanUserService.selectListByPid(e.getId());
            e.setUsers(users);
            StringBuilder sb = new StringBuilder();
            String diffcultis = e.getDiffcultis();
            if (diffcultis.contains("1")) {
                sb.append("初级");
            }
            if (diffcultis.contains("2")) {
                if (StringUtils.isNotEmpty(sb.toString())) {
                    sb.append("、");
                }
                sb.append("中级");
            }
            if (diffcultis.contains("3")) {
                if (StringUtils.isNotEmpty(sb.toString())) {
                    sb.append("、");
                }
                sb.append("高级");
            }
            e.setDiffcultisName(sb.toString());
            // 组装题库
            String bids = e.getBids();
            List<String> bs;
            if (bids.contains(",")) {
                String[] split = bids.split(",");
                bs = Arrays.asList(split);
            } else {
                bs = new ArrayList<>();
                bs.add(bids);
            }
            List<TsQuestionBank> banks = tsQuestionBankService.list(new QueryWrapper<TsQuestionBank>().in("id", bs));
            StringBuilder sb2 = new StringBuilder();
            for (TsQuestionBank t : banks) {
                if (StringUtils.isNotEmpty(t.getTitle())) {
                    sb2.append(t.getTitle());
                    sb2.append("、");
                }
            }
            if(sb2.toString().length()>0){
                e.setBidsName(sb2.substring(0,sb2.toString().length()-1));
            }

        }
        return page;

    }


    /**
     * 开始考试
     *
     * @param examPlanDto
     * @return
     */
    @Override
    public ExamQuestionsVo createExam(ExamPlanDto examPlanDto) {
        //生成考试信息
        Integer examId = addExam(examPlanDto);
        if (examId == 0) {
            return null;
        }
        return createExamQuestions(examPlanDto, examId);
    }

    /**
     * 查询考试管理
     *
     * @param examPlanDto
     * @return
     */
    @Override
    public IPage<ExamVo> queryExam(ExamPlanDto examPlanDto) {
        Page<ExamVo> page = new Page<>(examPlanDto.getCurrent(), examPlanDto.getSize());
        IPage<ExamVo> list = this.baseMapper.queryExam(page, examPlanDto.getOrgNo(), examPlanDto.getKeyword());
        for (ExamVo e : list.getRecords()) {
            StringBuilder sb = new StringBuilder();
            String diffcultis = e.getLevel();
            if (diffcultis.contains("1")) {
                sb.append("初级");
            }
            if (diffcultis.contains("2")) {
                if (StringUtils.isNotEmpty(sb.toString())) {
                    sb.append("、");
                }
                sb.append("中级");
            }
            if (diffcultis.contains("3")) {
                if (StringUtils.isNotEmpty(sb.toString())) {
                    sb.append("、");
                }
                sb.append("高级");
            }
            e.setLevelName(sb.toString());
            //对考试状态进行重新校验和更新
            updateExamStatus(e);
        }
        return list;
    }

    /**
     * 我的考试查询
     *
     * @param examPlanDto
     * @return
     */
    @Override
    public IPage<ExamVo> queryMyExam(ExamPlanDto examPlanDto) {
        Page<ExamVo> page = new Page<>(examPlanDto.getCurrent(), examPlanDto.getSize());
        IPage<ExamVo> list = this.baseMapper.queryMyExam(page, examPlanDto.getUserId());
        for (ExamVo e : list.getRecords()) {
            StringBuilder sb = new StringBuilder();
            String diffcultis = e.getLevel();
            if (diffcultis.contains("1")) {
                sb.append("初级");
            }
            if (diffcultis.contains("2")) {
                if (StringUtils.isNotEmpty(sb.toString())) {
                    sb.append("、");
                }
                sb.append("中级");
            }
            if (diffcultis.contains("3")) {
                if (StringUtils.isNotEmpty(sb.toString())) {
                    sb.append("、");
                }
                sb.append("高级");
            }
            e.setLevelName(sb.toString());
            //对考试状态进行重新校验和更新
            updateExamStatus(e);
        }
        return list;
    }

    private void updateExamStatus(ExamVo e){
        if(Objects.isNull(e.getExamTime())){
            return;
        }
        LocalDateTime endTime = e.getExamTime().plusSeconds(e.getLimitTime());
        Duration duration = Duration.between(e.getStartTime(), endTime);
        //对考试状态进行重新校验和更新
       if (endTime.compareTo(LocalDateTime.now()) < 0) {
            if(e.getStatus()<2){
                TsExam tsExam = new TsExam();
                tsExam.setId(e.getId());
                tsExam.setStatus(2);
                tsExam.setTotalTimes((int) duration.getSeconds());
                tsExam.setScore(finalScoring(e));
                tsExam.setUserTopicCnt(questionsAnsweredNum(e));
                tsExamService.updateById(tsExam);
                e.setStatus(2);
                e.setTotalTimes((int) duration.getSeconds());
                e.setScore(finalScoring(e));
                e.setUserTopicCnt(questionsAnsweredNum(e));
                e.setExamStatus("已结束");
            }

        }
    }
    /**
     * 计算总分
     * */
    private int finalScoring(ExamVo e){
        List<FinalScoring> finalScorings =  baseMapper.finalScoring(e.getId());
        AtomicInteger totalScore = new AtomicInteger();
        finalScorings.stream().forEach(u->{
            totalScore.addAndGet(u.getScore());
        } );
        return totalScore.get();
    }
    /**
     * 计算已答题数
     * */
    private int questionsAnsweredNum(ExamVo e){
        QueryWrapper<TsExamQuestion> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("eid",e.getId());
        queryWrapper.and( u->u.ne("answer","").and(s->s.isNotNull("answer")));
        int i = tsExamQuestionService.count(queryWrapper);
        return i;
    }
    /**
     * 保存用户成绩
     *
     * @param examDto
     * @return
     */
    @Transactional
    @Override
    public Boolean saveResult(ExamDto examDto) {

        if(ListUtils.isEmpty(examDto.getQuestions())){
            throw new RuntimeException("交卷题目数量为0");
        }
        TsExam tsExam =  tsExamService.getById(examDto.getId());
        Duration duration = Duration.between(tsExam.getStartTime(), LocalDateTime.now());
        examDto.setTotalTimes(duration.getSeconds());
        //答案不为空数量
        int topicCnt = examDto.getQuestions().stream().filter(q -> StringUtils.isNotBlank(q.getAnswer())).collect(Collectors.counting()).intValue();
        this.baseMapper.updateResult(examDto.getId(), examDto.getResult(), topicCnt, examDto.getTotalTimes(), examDto.getStatus());

        tsExamQuestionService.remove(new QueryWrapper<TsExamQuestion>().eq("eid", examDto.getId()));

        int res = this.baseMapper.insertBatchQuestions(examDto.getOrgNo(), examDto.getId(), examDto.getQuestions());
        //保存成绩
        return res > 0;
    }

    @Override
    public Boolean saveResultStep(TsExamQuestion tsExamQuestion) {
        QueryWrapper<TsExamQuestion> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("eid",tsExamQuestion.getEid());
        queryWrapper.eq("tid",tsExamQuestion.getTid());
        tsExamQuestion.setUtime(LocalDateTime.now());
        Boolean b = tsExamQuestionService.update(tsExamQuestion,queryWrapper);
        //用户已做题目数量
        TsExam tsExam = new TsExam();
        tsExam.setId(tsExamQuestion.getEid());
        tsExam.setUserTopicCnt(tsExamQuestion.getUserTopicCnt());
        tsExam.setUtime(LocalDateTime.now());
        Boolean boo = tsExamService.updateById(tsExam);
        return b;
    }


    /**
     * 练习题
     *
     * @return
     */
    @Override
    public TsExamQuestionVo practiceQuestion() {
        List<TsExamQuestionVo> list = selectQuestions("", "", 0, 1);
        TsExamQuestionVo tsExamQuestionVo = list.get(0);

        if (tsExamQuestionVo.getType() == 1 || tsExamQuestionVo.getType() == 2) {
            // 单选  多选
            StringBuilder sb = new StringBuilder();
            for (TsQuestionAnswer t : tsExamQuestionVo.getAnswers()) {
                if (t.getIsRight() == 1) {
                    if (StringUtils.isNotEmpty(sb.toString())) {
                        sb.append(",");
                    }
                    sb.append(t.getId());
                }
            }
            tsExamQuestionVo.setAnswer2(sb.toString());
        } else {
            tsExamQuestionVo.setAnswer2(tsExamQuestionVo.getAnswer());
        }
        return list.get(0);
    }

    /**
     * 查看考试结果
     *
     * @param id
     * @return
     */
    @Override
    public ExamVo queryExamResult(int id) {
        ExamVo examVo = this.baseMapper.selectExamResult(id);

        List<TsExamQuestionVo> questions = this.baseMapper.selectExamQuestionsResult(id);

        List<TsExamQuestionVo> danxuanQuestions = questions.stream().filter(q -> q.getType() == 1).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(danxuanQuestions)) {
            questionAddAnswer(danxuanQuestions, 1);
        }


        List<TsExamQuestionVo> duoxuanQuestions = questions.stream().filter(q -> q.getType() == 2).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(duoxuanQuestions)) {
            questionAddAnswer(duoxuanQuestions, 1);
        }

        List<TsExamQuestionVo> panduanQuestions = questions.stream().filter(q -> q.getType() == 3).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(panduanQuestions)) {
            questionAddAnswer(panduanQuestions, 1);
        }


        examVo.setDanxuanResult(danxuanQuestions);
        examVo.setDuoxuanResult(duoxuanQuestions);
        examVo.setPanduanResult(panduanQuestions);

        return examVo;
    }


    /**
     * 抽取考试题目
     *
     * @param examPlanDto
     * @return
     */
    public ExamQuestionsVo createExamQuestions(ExamPlanDto examPlanDto, Integer examId) {



        //考试难度
        String diff = examPlanDto.getDiffcultis();
        //所属题库
        String bids = examPlanDto.getBids();
        //模拟考试 默认单选20  多选15  判断15
        Integer danxuanNum = examPlanDto.getDanxuan();
        Integer duoxuanNum = examPlanDto.getDuoxuan();
        Integer panduanNum = examPlanDto.getPanduan();

        //查询考试计划中设置的考试题目
        if (examPlanDto.getExamType() == 2) {
            ExamVo examVo = this.baseMapper.selectExam(examPlanDto.getId());
            danxuanNum = examVo.getDanxuan();
            duoxuanNum = examVo.getDuoxuan();
            panduanNum = examVo.getPanduan();
            diff = examVo.getDiffcultis();
            bids = examVo.getBids();
        } else {
            //模拟考试 默认单选20  多选15  判断15
            danxuanNum = 20;
            duoxuanNum = 15;
            panduanNum = 15;
        }

        List<TsExamQuestionVo> danxuanQuestions = selectQuestions(diff, bids, 1, danxuanNum);
        List<TsExamQuestionVo> duoxuanQuestions = selectQuestions(diff, bids, 2, duoxuanNum);

        List<TsExamQuestionVo> panduanQuestions = selectQuestions(diff, bids, 3, panduanNum);

        ExamQuestionsVo examQuestionsVo = new ExamQuestionsVo();
        examQuestionsVo.setExamId(examId);
        examQuestionsVo.setDanxuan(danxuanQuestions);
        examQuestionsVo.setDuoxuan(duoxuanQuestions);
        examQuestionsVo.setPanduan(panduanQuestions);

        //保存试卷问题
        TsExamQuestion tsExamQuestion = new TsExamQuestion();
        tsExamQuestion.setEid(examId);
        tsExamQuestion.setOrgNo(examPlanDto.getOrgNo());
        tsExamQuestion.setAnswer("");
        tsExamQuestion.setUtime(LocalDateTime.now());
        for (TsExamQuestionVo t : danxuanQuestions) {
            tsExamQuestion.setTid(t.getId());
            tsExamQuestion.setId(null);
            tsExamQuestionService.save(tsExamQuestion);
        }
        for (TsExamQuestionVo t : duoxuanQuestions) {
            tsExamQuestion.setTid(t.getId());
            tsExamQuestion.setId(null);
            tsExamQuestionService.save(tsExamQuestion);
        }
        for (TsExamQuestionVo t : panduanQuestions) {
            tsExamQuestion.setTid(t.getId());
            tsExamQuestion.setId(null);
            tsExamQuestionService.save(tsExamQuestion);
        }

        return examQuestionsVo;
    }

    /**
     * 从题库随机获取题目
     *
     * @param diff         题目难度  多个以逗号拼接，全部为空
     * @param bids         题目所属题库 多个以逗号拼接  全部为空
     * @param questionType 题目类型 1单选  2多选 3判断  0随机
     * @param questionNum  抽取随机题目数量
     * @return
     */
    private List<TsExamQuestionVo> selectQuestions(String diff, String bids, int questionType, int questionNum) {
        List<TsExamQuestionVo> Questions = getQuestion(diff, bids, questionType, questionNum);
        if (!CollectionUtils.isEmpty(Questions)) {
            questionAddAnswer(Questions, questionType);
        }
        return Questions;
    }

    /**
     * 给题目增加选项
     *
     * @param questions
     * @param questionType 题目类型 1单选，2多选，3判断
     */
    public void questionAddAnswer(List<TsExamQuestionVo> questions, int questionType) {


        if (questionType == 3) {
            questions.stream().forEach(q -> {
                List<TsQuestionAnswer> answers = new ArrayList<>(2);
                TsQuestionAnswer right = new TsQuestionAnswer();
                right.setTitle("对");
                right.setId(1);
                TsQuestionAnswer wrong = new TsQuestionAnswer();
                wrong.setTitle("错");
                wrong.setId(2);
                if ("1".equals(q.getAnswer())) {
                    right.setIsRight(1);
                    wrong.setIsRight(0);
                } else {
                    right.setIsRight(0);
                    wrong.setIsRight(1);
                }
                answers.add(right);
                answers.add(wrong);
                q.setAnswers(answers);
                q.setAnswer2(q.getAnswer());
            });

        } else {
            List<TsQuestionAnswer> answers = tsQuestionAnswerService.getAnswer(questions.stream().map(q -> q.getId()).collect(Collectors.toList()));

            questions.stream().forEach(
                    q -> {
                        q.setAnswers(answers.stream().filter(a -> a.getTid().equals(q.getId())).collect(Collectors.toList()));
                    }
            );
            out:
            for (TsExamQuestionVo t : questions) {
                List<TsQuestionAnswer> answers1 = t.getAnswers();
                if (1 == t.getType().intValue()) {
                    in:
                    for (TsQuestionAnswer a : answers1) {
                        if (a.getIsRight().intValue() == 1) {
                            t.setAnswer2(a.getId().toString());
                            break in;
                        }
                    }
                } else if (2 == t.getType().intValue()) {
                    StringBuilder sb = new StringBuilder();
                    for (TsQuestionAnswer a : answers1) {
                        if (a.getIsRight().intValue() == 1) {
                            if (StringUtils.isNotEmpty(sb.toString())) {
                                sb.append(",");
                            }
                            sb.append(a.getId());
                        }
                    }
                    t.setAnswer2(sb.toString());
                }

            }
        }
    }

    /**
     * 新增人员考试信息
     *
     * @param examPlanDto
     * @return 考试信息ID
     */
    public Integer addExam(ExamPlanDto examPlanDto) {
        //如果是模拟考试
        if (examPlanDto.getExamType() == 1) {
            examPlanDto.setStatus(1);
            examPlanDto.setTitle("模拟考试");
            examPlanDto.setDanxuan(20);
            examPlanDto.setDuoxuan(15);
            examPlanDto.setPanduan(15);
            examPlanDto.setLimitTime(5400);
            examPlanDto.setScore(100);
            return this.baseMapper.addExam1(examPlanDto) > 0 ? examPlanDto.getExamId() : 0;
        } else {
            QueryWrapper<TsExam> tsExamQueryWrapper = new QueryWrapper<>();
            tsExamQueryWrapper.eq("uid",examPlanDto.getUserId());
            tsExamQueryWrapper.eq("pid",examPlanDto.getPid());
            tsExamQueryWrapper.eq("org_no",examPlanDto.getOrgNo());
            List<TsExam> tsExamList = tsExamService.list(tsExamQueryWrapper);
            if (!CollectionUtils.isEmpty(tsExamList)) {
                throw new RuntimeException("已经参加了该场考试，请选择继续考试");
            }
            //考试已生成
            TsExamPlan tsExamPlan = baseMapper.selectById(examPlanDto.getPid());
            examPlanDto.setTitle(tsExamPlan.getTitle());
            examPlanDto.setDanxuan(tsExamPlan.getDanxuan());
            examPlanDto.setDuoxuan(tsExamPlan.getDuoxuan());
            examPlanDto.setPanduan(tsExamPlan.getPanduan());
            examPlanDto.setLimitTime(tsExamPlan.getLimitTime());
            examPlanDto.setScore(tsExamPlan.getScore());
            examPlanDto.setDiffcultis(tsExamPlan.getDiffcultis());
            examPlanDto.setExamTime(new Date());
                        //设置考试类型为2 正式考试
            examPlanDto.setExamType(2);
            //设置考试状态 0新生成
            examPlanDto.setStatus(1);
            //增加考试记录
            return this.baseMapper.addExam2New(examPlanDto) > 0? examPlanDto.getId() : 0;
//            return this.baseMapper.updateExam(examPlanDto) > 0 ? examPlanDto.getId() : 0;
        }

    }

    /**
     * 随机抽取题目数量
     *
     * @param diff         难度，1初级，2中级，3高级；可多选、多个以逗号拼接
     * @param bids         所属题库 可多选 ，多个题库id以逗号拼接;可为空或者null
     * @param questionType 题目类型 1单选，2多选，3判断
     * @param questionNum  题目数量
     * @return
     */
    public List<TsExamQuestionVo> getQuestion(String diff, String bids, int questionType, int questionNum) {

        return this.baseMapper.queryRoundQuestions(diff, bids, questionType, questionNum);
    }

}
